#include <iostream>
#include <cstring>

class String {
private:
    char* data;
    size_t len;

public:
    // 构造函数
    String(const char* str) : len(strlen(str)) {
        data = new char[len + 1];
        std::strcpy(data, str);
    }

    // 移动构造函数
    String(String&& other) noexcept : len(other.len), data(other.data) {
        // 移动资源后，将源对象的指针设置为nullptr，以避免悬空指针
        other.data = nullptr;
        other.len = 0;
    }

    // 析构函数
    ~String() {
        delete[] data;
    }

    // 禁用拷贝构造函数和拷贝赋值运算符
    String(const String&) = delete;
    String& operator=(const String&) = delete;

    // ... 其他成员函数，如输出等 ...

    void print() const {
        std::cout << data << std::endl;
    }
};

int main() {
    // 使用常规构造函数创建一个String对象
    String s1("Hello, World!");

    // 使用移动构造函数从s1创建一个新的String对象s2
    // 注意：这里我们使用std::move()来将s1转换为右值引用
    String s2(std::move(s1));

    // 现在s2拥有s1的资源，s1的data指针是nullptr
    // 尝试使用s1可能会导致未定义的行为

    // 输出s2的内容（应该与s1的原始内容相同）
    s2.print();  // 输出: Hello, World!

    // s1的data指针是nullptr，尝试输出可能会导致崩溃或其他未定义行为
    // 最好不要尝试使用已经被移动的s1对象

    return 0;
}
